﻿Imports System.Net.Sockets

Public Class BufferManager

    Private m_current As LinkedListNode(Of BufferChunkManage)
    ''' <summary>
    ''' 一个区域包含的块数量
    ''' </summary>
    Private mAreaChunksize As Integer
    ''' <summary>
    ''' 一个块包含的内存大小
    ''' </summary>
    Private mChunkSize As Integer

    ''' <summary>
    ''' 使用过后重新放入缓冲区的块
    ''' </summary>
    Private mChunkStack As Stack(Of BufferChunk)

    ''' <summary>
    ''' 每个区域包含一个大的内存块，一个大内存块包含很多小内存块
    ''' </summary>
    Private mAreas As LinkedList(Of BufferChunkManage)
    ''' <summary>
    ''' 一个块包含的内存大小
    ''' </summary>
    Public ReadOnly Property ChunkSize As Integer
        Get
            Return mChunkSize
        End Get
    End Property



    ''' <summary>
    ''' 创建一个默认缓冲区管理器，默认每个区域1M内存 一个内存块8K
    ''' </summary>
    Public Sub New()
        Me.New(256, 4096)
    End Sub
    ''' <summary>
    ''' 创建一个缓冲区管理器
    ''' </summary>
    ''' <param name="areaChunksize">一个区域包含的块数量</param>
    ''' <param name="chunkSize">一个块包含的内存大小</param>
    Public Sub New(ByVal areaChunksize As Integer, ByVal chunkSize As Integer)
        mAreaChunksize = areaChunksize
        mChunkSize = chunkSize
        mChunkStack = New Stack(Of BufferChunk)
        mAreas = New LinkedList(Of BufferChunkManage)
        m_current = Nothing
    End Sub

    ''' <summary>
    ''' 获取一个缓冲区
    ''' </summary>
    ''' <returns>缓冲区</returns>
    Public Function GetBuffer(） As BufferChunk
        Dim buf As BufferChunk = Nothing
        SyncLock mAreas
            If mChunkStack.Count > 0 Then
                Return mChunkStack.Pop()
            End If

            Dim manage As BufferChunkManage
            If m_current Is Nothing Then
                '区域为空，则新建一个区域
                manage = New BufferChunkManage(mAreaChunksize, mChunkSize)
                m_current = mAreas.AddLast(manage)
                manage.Node = m_current
            Else
                manage = m_current.Value
            End If

            If Not manage.GetBuffer(buf) Then
                m_current = m_current.Next '本区域没有，进入下一个区域
                Return GetBuffer()
            End If
        End SyncLock

        Return buf
    End Function

    ''' <summary>
    ''' 释放缓冲区
    ''' </summary>
    ''' <param name="buf"></param>
    Public Sub FreeBuffer(buf As BufferChunk)
        If buf Is Nothing Then Return
        If buf.Manage Is Nothing Then Return
        If buf.Manage.Node Is Nothing Then Return
        SyncLock mAreas
            'm_current = buf.Manage.Node '更改节点未当前节点
            mChunkStack.Push(buf)
            buf.ReadableBytes = 0
            'buf.Manage.FreeBuffer(buf)
        End SyncLock

    End Sub
End Class
